package com.jingdianjichi.oss.util;

import com.jingdianjichi.oss.entity.FileInfo;
import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * MinIO文件操作工具类
 * 提供了一系列操作MinIO服务器的方法，包括创建存储桶（Bucket）、上传文件、列出存储桶、
 * 列出文件、下载文件、删除存储桶和删除文件等功能。
 *
 * @author: WuYimin
 * Date: 2024-02-07
 */
@Component
public class MinioUtil {

	@Resource
	private MinioClient minioClient;

	/**
	 * 创建存储桶
	 * 如果指定的存储桶不存在，则创建它。
	 *
	 * @param bucket 存储桶名称
	 * @throws Exception 如果操作失败
	 */
	public void createBucket(String bucket) throws Exception {
		boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
		if (!exists) {
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
		}
	}

	/**
	 * 上传文件到MinIO
	 *
	 * @param inputStream 文件的输入流
	 * @param bucket 存储桶名称
	 * @param objectName 文件在存储桶中的对象名称
	 * @throws Exception 如果操作失败
	 */
	public void uploadFile(InputStream inputStream, String bucket, String objectName) throws Exception {
		minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
				.stream(inputStream, -1, Integer.MAX_VALUE).build());
	}

	/**
	 * 列出所有存储桶的名称
	 *
	 * @return 存储桶名称列表
	 * @throws Exception 如果操作失败
	 */
	public List<String> getAllBucket() throws Exception {
		List<Bucket> buckets = minioClient.listBuckets();
		return buckets.stream().map(Bucket::name).collect(Collectors.toList());
	}

	/**
	 * 列出指定存储桶中的所有文件
	 *
	 * @param bucket 存储桶名称
	 * @return 文件信息列表
	 * @throws Exception 如果操作失败
	 */
	public List<FileInfo> getAllFile(String bucket) throws Exception {
		Iterable<Result<Item>> results = minioClient.listObjects(
				ListObjectsArgs.builder().bucket(bucket).build());
		List<FileInfo> fileInfoList = new LinkedList<>();
		for (Result<Item> result : results) {
			FileInfo fileInfo = new FileInfo();
			Item item = result.get();
			fileInfo.setFileName(item.objectName()); // 设置文件名称
			fileInfo.setDirectoryFlag(item.isDir()); // 设置是否为目录
			fileInfo.setEtag(item.etag()); // 设置ETag值
			fileInfoList.add(fileInfo);
		}
		return fileInfoList;
	}

	/**
	 * 从MinIO下载文件
	 *
	 * @param bucket 存储桶名称
	 * @param objectName 文件对象名称
	 * @return 文件的输入流
	 * @throws Exception 如果操作失败
	 */
	public InputStream downLoad(String bucket, String objectName) throws Exception {
		return minioClient.getObject(
				GetObjectArgs.builder().bucket(bucket).object(objectName).build()
		);
	}

	/**
	 * 删除存储桶
	 *
	 * @param bucket 要删除的存储桶名称
	 * @throws Exception 如果操作失败
	 */
	public void deleteBucket(String bucket) throws Exception {
		minioClient.removeBucket(
				RemoveBucketArgs.builder().bucket(bucket).build()
		);
	}

	/**
	 * 删除存储桶中的文件对象
	 *
	 * @param bucket 存储桶名称
	 * @param objectName 文件对象名称
	 * @throws Exception 如果操作失败
	 */
	public void deleteObject(String bucket, String objectName) throws Exception {
		minioClient.removeObject(
				RemoveObjectArgs.builder().bucket(bucket).object(objectName).build()
		);
	}
}
